﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Threading;


namespace CCPSIP.Message
{
    /// <summary>CCPSIP_010：發送文字訊息 API</summary>
    /// idHeader = 裝置 UUID 前八碼。iOS 請使用 [CCPCrypto getIdHeader] 呼叫。
    /// checkcode = 裝置限時驗證碼。iOS 請使用 [CCPCrypto getCheckcode] 呼叫。
    /// ChatID = 聊天ID(對方帳號或ClientGID)。
    /// localPID = 發訊方的本機訊息ID。
    /// message = 訊息全文。

    public class send_text : IHttpHandler
    {
        private const string kMsgType = "T";
        private const int kMsgPreviewLength = 20;
        private const string kDateTimeFormat = "yyyy/MM/dd HH:mm:ss";

        private const string kCommandHead = "@CMD_";
        private const string kServiceIdKey = "SERVICE_ID";


        public void ProcessRequest(HttpContext context)
        {
            HttpRequest req = context.Request;
            HttpResponse resp = context.Response;
            resp.ContentType = "text/plain";
            resp.ContentEncoding = System.Text.Encoding.UTF8;
            DateTime reqTime = DateTime.Now;
            string resultStr = "";

            try
            {
                //【01】取得POST參數，驗證身分
                //
                string idHeader = req.Form["idHeader"];
                string checkcode = req.Form["checkcode"];
                string ChatID = req.Form["ChatID"];//聊天ID(對方帳號或ClientGID)
                int localPID = -1;//發訊方的本機訊息ID
                string message = req.Form["message"];//訊息全文


                try
                {
                    ChatID = ChatID.Trim();
                    localPID = Convert.ToInt32(req.Form["localPID"]);
                }
                catch
                {
                    throw new Exception("Error_01: Parameter Error");//參數錯誤
                }


                SipUserInfo userInfo = SipKit.GetUserInfo(idHeader, checkcode, req);
                if (userInfo == null)
                {
                    throw new Exception("Error_02: Cannot identify this device");//無法識別此裝置
                }


                //【02】產生訊息摘要
                //
                string msgPreview = message.Replace("\r\n", " ").Replace("\n", " ");
                if (msgPreview.Length > kMsgPreviewLength)
                    msgPreview = msgPreview.Substring(0, kMsgPreviewLength - 3) + "...";
                msgPreview = string.Format("{0}: {1}", userInfo.CustomName, msgPreview);


                //【03】儲存訊息
                //
                long MsgID = 0;
                bool isToRobot = RobotKit.isRobot(ChatID);
                RobotServiceInfo[] services = null;
                bool isFromRobot = RobotKit.isRobot(userInfo.SIP_Num);
                bool isGroupMsg = SipKit.isGroupID(ChatID);


                //【03-1】傳給Debug機器人的訊息略過
                //
                if (ChatID == "RobotDebug")
                {
                    Dictionary<string, string> debugDict = new Dictionary<string, string>();
                    debugDict["MsgID"] = Convert.ToString(-1);
                    debugDict["MsgTime"] = reqTime.ToString(kDateTimeFormat);
                    debugDict["LocalPID"] = Convert.ToString(localPID);
                    resp.ContentType = "application/json";
                    fastJSON.JSON.Instance.Parameters.EnableAnonymousTypes = true;
                    resultStr = fastJSON.JSON.Instance.ToJSON(debugDict);
                    return;
                }


                //【03-2】檢查機器人Service權限
                //
                if (isToRobot)
                {
                    string ROBOT_ID = ChatID;
                    services = RobotKit.getServices(userInfo, ROBOT_ID);
                    if (services.Length == 0)
                    {
                        throw new Exception("Error_03: You have no right to use this robot");//無機器人權限
                    }
                }


                if (isGroupMsg)
                {
                    if (!OracleKitGroup.isMemberOfGroup(userInfo.SIP_Num, ChatID))
                    {
                        throw new Exception("Error_04: You are not a member");//你不是群組成員
                    }
                    MsgID = OracleKitMsg.InsertGroupMsg(userInfo, ChatID, kMsgType, msgPreview, message, localPID, reqTime);
                }
                else
                {
                    MsgID = OracleKitMsg.InsertMsgOne(userInfo.SIP_Num, ChatID, kMsgType, msgPreview, message, localPID, reqTime);
                }


                //【04】呼叫機器人
                //
                if (isToRobot)
                {
                    string ROBOT_ID = ChatID;
                    string Command = message;
                    if (Command.StartsWith(kCommandHead))
                    {
                        Command = Command.Substring(kCommandHead.Length);
                    }


                    //【04-2】導向至對應的Service
                    //
                    RobotServiceInfo rService = services[0];
                    if (services.Length > 1)
                    {
                        Dictionary<string, string> paramDict = ChrisKit.DictFromQueryStr(Command);
                        if (paramDict.ContainsKey(kServiceIdKey))
                        {
                            string targetID = paramDict[kServiceIdKey];
                            foreach (RobotServiceInfo service in services)
                            {
                                if (service.SERVICE_ID == targetID)
                                {
                                    rService = service;
                                    break;
                                }
                            }
                        }
                    }


                    //【04-3】記錄後，呼叫機器人Service
                    //
                    string decodedCmd = HttpUtility.UrlDecode(Command);
                    OracleKitRobot.InsertMsgOneRobot("U", userInfo.SIP_Num, ROBOT_ID, rService.SERVICE_ID, MsgID, decodedCmd, reqTime);

                    ServiceCallParam sParamObj = new ServiceCallParam(userInfo, rService, Command);
                    new Thread(new ParameterizedThreadStart(CallService)).Start(sParamObj);


                    //【04-4】檢查機器人Service是否有回應
                    //
                    RobotCheckParam cParamObj = new RobotCheckParam(userInfo, rService, reqTime);
                    new Thread(new ParameterizedThreadStart(OracleKitRobot.CheckRobotReply)).Start(cParamObj);
                }


                //【05】Log機器人回覆
                //
                if (isFromRobot && (!isGroupMsg))
                {
                    string ROBOT_ID = userInfo.SIP_Num;
                    OracleKitRobot.InsertMsgOneRobot("R", ChatID, ROBOT_ID, ROBOT_ID, MsgID, message, reqTime);
                }


                //【97】通知Push Service
                //
                PushKit.WakePushAsync(PushKit.PushType.Msg);


                if (!isToRobot)
                {
                    //【98】傳送 Windows CCP MSG 通知
                    //
                    if (isGroupMsg)
                    {
                        ChatGroupMember[] Members = OracleKitGroup.getMembers(ChatID);
                        foreach (ChatGroupMember member in Members)
                        {
                            if (member.MemberID == userInfo.SIP_Num)
                                continue;//略過發訊人
                            else if (SipKit.isHQMobileExt(member.MemberID))
                                MSGKit.SendTextHQAsync(member.MemberID, msgPreview);
                        }
                    }
                    else
                    {
                        if (SipKit.isHQMobileExt(ChatID))
                            MSGKit.SendTextHQAsync(ChatID, msgPreview);
                    }
                }


                //【99】回傳結果
                //
                Dictionary<string, string> resultDict = new Dictionary<string, string>();
                resultDict["MsgID"] = Convert.ToString(MsgID);
                resultDict["MsgTime"] = reqTime.ToString(kDateTimeFormat);
                resultDict["LocalPID"] = Convert.ToString(localPID);

                resp.ContentType = "application/json";
                resp.Charset = null;
                fastJSON.JSON.Instance.Parameters.EnableAnonymousTypes = true;
                resultStr = fastJSON.JSON.Instance.ToJSON(resultDict);
            }
            catch (Exception ex)
            {
                resp.ContentType = "application/xml";
                resultStr = ChrisKit.Ex2Xml(ex, false);
            }
            finally
            {
                int contentLength = resp.ContentEncoding.GetByteCount(resultStr);
                resp.AppendHeader("Content-Length", contentLength.ToString());
                resp.Write(resultStr);
                resp.Flush();
                resp.Close();
            }
        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }


        #region 機器人Service呼叫

        /// <summary>
        /// 呼叫機器人Service
        /// </summary>
        /// <param name="param">ServiceCallParam參數物件</param>
        private void CallService(object param)
        {
            if (param is ServiceCallParam)
            {
                ServiceCallParam p = (ServiceCallParam)param;
                RobotKit.CallService(p.UserInfo, p.ServiceInfo, p.Command);
            }
        }


        /// <summary>
        /// 機器人服務呼叫Parameters
        /// </summary>
        private class ServiceCallParam
        {
            private SipUserInfo _UserInfo;
            private RobotServiceInfo _ServiceInfo;
            private string _Command;

            public SipUserInfo UserInfo { get { return this._UserInfo; } }
            public RobotServiceInfo ServiceInfo { get { return this._ServiceInfo; } }
            public string Command { get { return this._Command; } }


            public ServiceCallParam(SipUserInfo userInfo, RobotServiceInfo service, string Command)
            {
                _UserInfo = userInfo;
                _ServiceInfo = service;
                _Command = Command;
            }
        }

        #endregion


    }
}
